package synchronized_;

import Lock_.LockTest;

import java.util.concurrent.locks.ReentrantLock;

/*
* wait()、notify（）、notifyAll（）的使用
*
* 1、wait() ：一旦使用该方法，当前线程进入阻塞状态，并且释放同步监视器（释放锁）
* 2、notify（）：一旦使用该方法，就会唤醒被wait()的线程。如果有多个线程被wait（），那么唤醒优先级高的
* 3、notifyAll（）：唤醒所有被wait（）的方法
* 说明：
* 1、wait()、notify（）、notifyAll（）方法必须使用在同步代码块和同步方法中
* 2、wait()、notify（）、notifyAll（）这三个方法是由Object类提供的，因此所有的类都能调用
* 3、同步监视器对象（锁对象）必须与wait()、notify（）、notifyAll（）调用的对象相同，否则会报TLleqaLMonitorStateException异常

 * */
public class WaitAndNotify implements Runnable {

    private int ticket  = 100;

    Object object = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (object){

                /*
                * 1、唤醒一个被wait（）的线程锁，此时这个线程还没有得到锁，需要等待其他线程释放锁
                * */
                System.out.println(Thread.currentThread().getName()+"当前线程获得锁");
                object.notify();
                System.out.println(Thread.currentThread().getName()+"唤醒了一个线程");
                if (ticket > 0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+":"+ticket);
                    ticket--;
                    try {
                        /*
                         * 2、当前线程进入睡眠状态，并释放锁
                         * */
                        object.wait();
                        System.out.println(Thread.currentThread().getName()+"释放了锁");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else {
                    break;
                }
            }


        }
    }
}
class WaitAndNotifyMain{
    public static void main(String[] args) {
        WaitAndNotify waitAndNotify = new WaitAndNotify();
        Thread t1 = new Thread(waitAndNotify);
        Thread t2 = new Thread(waitAndNotify);
        Thread t3 = new Thread(waitAndNotify);
        t1.setName("线程一");
        t2.setName("线程二");
        t3.setName("线程三");
        t1.start();
        t2.start();
        t3.start();

    }
}
